<!DOCTYPE html>
<html>
<head>
    <title>Pendulum Diagram</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <canvas id="physicsCanvas" width="550" height="450"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        /**
         * Draws an arrowhead at the end of a line.
         * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
         * @param {number} fromX - The starting x-coordinate of the line.
         * @param {number} fromY - The starting y-coordinate of the line.
         * @param {number} toX - The ending x-coordinate of the line (where the arrow is).
         * @param {number} toY - The ending y-coordinate of the line (where the arrow is).
         * @param {number} headLength - The length of the arrowhead sides.
         */
        function drawArrowhead(ctx, fromX, fromY, toX, toY, headLength) {
            const angle = Math.atan2(toY - fromY, toX - fromX);
            ctx.save();
            ctx.beginPath();
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - headLength * Math.cos(angle - Math.PI / 6), toY - headLength * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - headLength * Math.cos(angle + Math.PI / 6), toY - headLength * Math.sin(angle + Math.PI / 6));
            ctx.stroke();
            ctx.restore();
        }

        /**
         * Draws a hatched ceiling support.
         * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
         * @param {number} x - The center x-coordinate of the support.
         * @param {number} y - The y-coordinate of the support line.
         * @param {number} width - The total width of the support.
         */
        function drawCeiling(ctx, x, y, width) {
            ctx.save();
            ctx.lineWidth = 1.5;
            // Main line
            ctx.beginPath();
            ctx.moveTo(x - width / 2, y);
            ctx.lineTo(x + width / 2, y);
            ctx.stroke();

            // Hatching
            const hatchLength = 10;
            const hatchAngle = Math.PI / 4;
            for (let i = x - width / 2; i <= x + width / 2; i += 8) {
                ctx.beginPath();
                ctx.moveTo(i, y);
                ctx.lineTo(i - hatchLength * Math.cos(hatchAngle), y - hatchLength * Math.sin(hatchAngle));
                ctx.stroke();
            }
            ctx.restore();
        }

        /**
         * Draws a complete pendulum system.
         * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
         * @param {number} centerX - The horizontal center for the pendulum drawing.
         * @param {string} type - The type of disk center, 'hollow' or 'filled'.
         */
        function drawPendulum(ctx, centerX, type) {
            // --- Parameters ---
            const pivot = { x: centerX, y: 60 };
            const l = 200; // length from pivot to disk center
            const r = 40;  // radius of the disk
            const angleFromVertical = 20 * Math.PI / 180;
            const pivotRadius = 6;
            const rodHalfWidth = 4;
            const centerPointRadius = 4;

            // --- Calculated Positions ---
            const diskCenter = {
                x: pivot.x + l * Math.sin(angleFromVertical),
                y: pivot.y + l * Math.cos(angleFromVertical)
            };
            
            // --- Direction Vectors ---
            const u = { // unit vector along the rod
                x: Math.sin(angleFromVertical),
                y: Math.cos(angleFromVertical)
            };
            const p = { // perpendicular vector to the rod
                x: -u.y,
                y: u.x
            };

            // --- Drawing ---
            ctx.strokeStyle = 'black';
            ctx.fillStyle = 'black';

            // 1. Draw Ceiling
            drawCeiling(ctx, pivot.x, pivot.y, 120);

            // 2. Draw Rod (as two parallel lines)
            ctx.save();
            ctx.lineWidth = 1.5;
            ctx.beginPath();
            ctx.moveTo(pivot.x + p.x * rodHalfWidth, pivot.y + p.y * rodHalfWidth);
            ctx.lineTo(diskCenter.x + p.x * rodHalfWidth, diskCenter.y + p.y * rodHalfWidth);
            ctx.moveTo(pivot.x - p.x * rodHalfWidth, pivot.y - p.y * rodHalfWidth);
            ctx.lineTo(diskCenter.x - p.x * rodHalfWidth, diskCenter.y - p.y * rodHalfWidth);
            ctx.stroke();
            ctx.restore();

            // 3. Draw Pivot (fill white to create clean joint, then stroke)
            ctx.save();
            ctx.lineWidth = 1.5;
            ctx.fillStyle = 'white';
            ctx.beginPath();
            ctx.arc(pivot.x, pivot.y, pivotRadius, 0, 2 * Math.PI);
            ctx.fill();
            ctx.stroke();
            ctx.restore();

            // 4. Draw Disk (fill white to create clean joint, then stroke)
            ctx.save();
            ctx.lineWidth = 1.5;
            ctx.fillStyle = 'white';
            ctx.beginPath();
            ctx.arc(diskCenter.x, diskCenter.y, r, 0, 2 * Math.PI);
            ctx.fill();
            ctx.stroke();
            ctx.restore();
            
            // 5. Draw Disk Center Point
            ctx.save();
            ctx.beginPath();
            ctx.arc(diskCenter.x, diskCenter.y, centerPointRadius, 0, 2 * Math.PI);
            if (type === 'filled') {
                ctx.fillStyle = 'black';
                ctx.fill();
            } else { // hollow
                ctx.fillStyle = 'white';
                ctx.fill();
                ctx.lineWidth = 1.5;
                ctx.stroke();
            }
            ctx.restore();

            // 6. Draw Dimension Lines and Labels
            ctx.save();
            ctx.lineWidth = 1;
            ctx.font = 'italic 20px Times New Roman';

            // Dimension for 'l'
            ctx.beginPath();
            ctx.moveTo(pivot.x, pivot.y);
            ctx.lineTo(diskCenter.x, diskCenter.y);
            ctx.stroke();
            drawArrowhead(ctx, pivot.x, pivot.y, diskCenter.x, diskCenter.y, 10);
            drawArrowhead(ctx, diskCenter.x, diskCenter.y, pivot.x, pivot.y, 10);
            const l_text_pos = {
                x: (pivot.x + diskCenter.x) / 2 + p.x * 20,
                y: (pivot.y + diskCenter.y) / 2 + p.y * 20
            };
            ctx.fillText('l', l_text_pos.x - 5, l_text_pos.y + 5);

            // Dimension for 'r'
            const r_angle = 15 * Math.PI / 180;
            const r_end_point = {
                x: diskCenter.x + r * Math.cos(r_angle),
                y: diskCenter.y + r * Math.sin(r_angle)
            };
            ctx.beginPath();
            ctx.moveTo(diskCenter.x, diskCenter.y);
            ctx.lineTo(r_end_point.x, r_end_point.y);
            ctx.stroke();
            drawArrowhead(ctx, diskCenter.x, diskCenter.y, r_end_point.x, r_end_point.y, 10);
            ctx.fillText('r', diskCenter.x + r * 0.7, diskCenter.y + r * 0.1);


            // Label 'O' at pivot
            ctx.fillText('O', pivot.x + 12, pivot.y + 5);

            ctx.restore();
        }

        // --- Main Drawing ---
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // Draw Pendulum (a)
        drawPendulum(ctx, 160, 'hollow');
        ctx.font = '20px Times New Roman';
        ctx.fillText('(a)', 155, 380);

        // Draw Pendulum (b)
        drawPendulum(ctx, 390, 'filled');
        ctx.font = '20px Times New Roman';
        ctx.fillText('(b)', 385, 380);

        // Draw Caption
        ctx.font = '20px "SimSun", "Songti SC"';
        ctx.fillStyle = 'black';
        ctx.fillText('习题 10-11 图', 210, 420);

    </script>
</body>
</html>